package com.microframework.base.core.security.token;

import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.SecretKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.microframework.base.core.exception.NotAuthorizedException;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import io.jsonwebtoken.security.WeakKeyException;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

/**
 * Token解析器 - 用于创建和解析JWT令牌
 */
@Component
@Slf4j
public class TokenParser {

	/**
	 * 令牌秘钥
	 */
	@Value("${jwt.secret:XbUM7dWpAbsB9sw8ditwyYwuxcjxFbiOdJ577T+yLaQ=}")
	private String secret;

    @Value("${jwt.access-token-expiration}")
    private long accessTokenExpiration;

    @Value("${jwt.refresh-token-expiration}")
    private long refreshTokenExpiration;

    private SecretKey signingKey;

    @PostConstruct
    public void init() {
        if (secret == null || secret.isEmpty()) {
            throw new IllegalStateException("JWT密钥未配置");
        }
        try {
            byte[] keyBytes = Base64.getDecoder().decode(secret);
            validateKeyLength(keyBytes);
            this.signingKey = Keys.hmacShaKeyFor(keyBytes);
            log.info("JWT密钥初始化成功，密钥长度: {}位", keyBytes.length * 8);
        } catch (IllegalArgumentException e) {
            throw new WeakKeyException("无效的Base64密钥: " + e.getMessage());
        }
    }

    private void validateKeyLength(byte[] keyBytes) {
        if (keyBytes.length < 32) {
            throw new WeakKeyException("密钥长度不足。要求至少256位(32字节)，当前: " + 
                                     (keyBytes.length * 8) + "位");
        }
    }

    public String generateAccessToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        return createToken(claims, accessTokenExpiration);
    }

    public String generateRefreshToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        return createToken(claims, refreshTokenExpiration);
    }

    public long getAccessTokenExpiration() {
        return accessTokenExpiration;
    }

    public long getRefreshTokenExpiration() {
        return refreshTokenExpiration;
    }

    private String createToken(Map<String, Object> claims, long expirationMillis) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Date expiration = new Date(nowMillis + expirationMillis);
        
        log.debug("创建Token - 签发时间: {}, 过期时间: {}", now, expiration);
        
        return Jwts.builder()
                .claims(claims)
                .issuedAt(now)
                .expiration(expiration)
                .signWith(signingKey, Jwts.SIG.HS256)
                .compact();
    }

    public Claims parseToken(String token) {
        try {
            return Jwts.parser()
                    .verifyWith(signingKey)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
                    
        } catch (ExpiredJwtException e) {
            throw new NotAuthorizedException("Token已过期.");
        } catch (UnsupportedJwtException e) {
            throw new NotAuthorizedException("不支持的Token类型.");
        } catch (MalformedJwtException e) {
            throw new NotAuthorizedException("Token格式错误.");
        } catch (SignatureException e) {
            throw new NotAuthorizedException("签名验证失败.");
        } catch (SecurityException e) {
            throw new NotAuthorizedException("安全异常.");
        } catch (IllegalArgumentException e) {
            throw new NotAuthorizedException("无效参数.");
        } catch (JwtException e) {
            throw new NotAuthorizedException("Token处理失败.");
        }
    }

    /**
     * 验证令牌有效性
     */
    public boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            return claims != null && !isTokenExpired(claims);
        } catch (Exception e) {
            log.error("验证Token失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 从令牌中获取用户ID
     */
    public String getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        if (claims == null) {
            return null;
        }
        
        // 安全获取用户ID
        Object userId = claims.get("userId");
        return userId != null ? userId.toString() : null;
    }

    /**
     * 判断令牌是否过期
     */
    private boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
    
    /**
     * 生成安全密钥（仅用于开发/测试）
     */
    public static String generateSecureKey() {
        SecretKey newKey = Jwts.SIG.HS256.key().build();
        return Base64.getEncoder().encodeToString(newKey.getEncoded());
    }
}